import { CrsClient } from "./crsClient";
import { CryptoJS } from "./CryptoJS";
import {
    AnimationMixer,
    $cancelAnimationFrame,
    $requestAnimationFrame,
    $window,
    AmbientLight,
    DirectionalLight,
    PerspectiveCamera,
    PLATFORM,
    Scene,
    ACESFilmicToneMapping,
    sRGBEncoding,
    TextureLoader,
    WebGL1Renderer,
    Vector3,
    LoopOnce,
    Clock,
} from "three-platformize";
console.log($cancelAnimationFrame, "对象");
import { toEnvMap } from "three-platformize/tools/toEnvMap";
import { WechatPlatform } from "three-platformize/src/WechatPlatform";
import { GLTF, GLTFLoader } from "three-platformize/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three-platformize/examples/jsm/controls/OrbitControls";

const app = getApp();
const avatarSound = app.globalData.innerAudioContext;

const systemInfo = wx.getSystemInfoSync();

Page({
    data: {
        // showOverlay: true,
        // showSelect: false,
        // SELECT_TYPE: SELECT_TYPE,
        // selectType: 0,
        // canvasW: width * 0.8, //画布宽度
        canvasType: false,

        //CRS配置
        config: {
            apiKey: "07241bad92e18131aa6e76e8d4247ca4", // EasyAR开发中心 - API KEY - API Key
            apiSecret: "29c1c04afe5e85664ee0dc6c1f4c6856d3c6b2cf62dcdb5a3502b140110e98f9", // EasyAR开发中心 - API KEY - API Secret
            crsAppId: "3130d2f4e71d630e59d55565b9ce2585", // EasyAR开发中心 - 云服务 - 云识别管理 - 云识别库信息 - CRS AppId
            token: "",
            clientHost: "https://cn1-crs.easyar.com:8443", //服务器一般不变
            jpegQuality: 0.7, //JPEG压缩质量，建议不低于70%
            minInterval: 1000, //最短的两次CRS请求间隔
        },
        //识别到这个数组中的ID就触发内容
        targetIds: [
            // "TODO 云识别管理 - 某个图库 - 识别图 - 某个识别图的ID",
            // "9785213a-f1ac-4a2b-9cdc-c866ce3bec91"
            {
                id: "a26f6b67-5731-48c7-a530-90b2d8d09cce",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_2.png",
                name: "亿升路口",
            },
            {
                id: "a3965639-b40c-4043-9d01-5a071b7f5abb",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_11.png",
                name: "仪表厂",
            },
            {
                id: "8d18ab23-69c2-44b7-9cce-7489f7aba8db",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_6.png",
                name: "一品馄饨",
            },
            {
                id: "f3553c97-4265-4afa-a6a7-53a5ae61dcf2",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_3.png",
                name: "五三路口",
            },

            {
                id: "a6191583-394e-407a-bc5d-78ed00f74695",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_9.png",
                name: "上饶客车站",
            },

            {
                id: "a042d7d1-304e-4da2-9c4a-bad69d81807d",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_10.png",
                name: "陆羽泉啤酒厂",
            },

            {
                id: "fc7eb5f9-fc75-489f-99cb-2ebd9f55735b",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_8.png",
                name: "老四夜宵酒店",
            },

            {
                id: "9440778f-6353-4e6d-858d-cae4781171c6",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_12.png",
                name: "兰凤娜包子铺",
            },

            {
                id: "84f864d7-3a57-4727-85b1-cafcbdfdcb32",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_13.png",
                name: "江光厂",
            },
            {
                id: "b1bc2c04-3626-49a6-873c-239ea4363f2c",
                img: "https://txcy.oss-cn-hangzhou.aliyuncs.com/point_cont_5.png",
                name: "弘餐厅",
            },
        ],

        showLoading: false,
        showLoadingText: "",
        status: 2,
        id: "",
        showResult: false,
        canvasId: "",
        showText: false,
        showCamera: false,
        showModel: true,
        currentImg: "",
    },

    disposing: false,
    platform: null as unknown as WechatPlatform,
    frameId: -1,

    listener: null as unknown as WechatMiniprogram.CameraFrameListener,
    canvas: null as unknown as WechatMiniprogram.Canvas,

    /** @type {boolean} 是否需要持续识别，在点击“识别体验”之后和识别成功之前为true */
    runningCrs: false,
    /** @type {boolean} 当前是否正在进行CRS请求 */
    busy: false,
    /** @type {CrsClient} 负责发起CRS请求的对象 */
    crsClient: null as unknown as CrsClient,
    /** @type {number} 最后一次CRS请求的事件，用于判断是否满足最短请求间隔 */
    last: null as unknown as number,
    mixer: AnimationMixer,
    currentScene: null as unknown as Scene,
    animal: null,

    onReady() {
        if (systemInfo.platform === "devtools") {
            //开发工具不会触发initdone事件，于是在onReady手动触发
            this.onCameraInit();
        }

        // 获取token
        this.queryToken()
            .then((msg) => {
                this.data.config.token = msg.result.token;
            })
            .catch((err) => {
                console.info(err);
            });

        // setTimeout(function () {
        //   // 3d模型加载，语音讲解
        //   wx.createSelectorQuery()
        //     .select("#mainCanvas")
        //     .node()
        //     .exec((res) => {
        //       const canvas = res[0].node;
        //       self.canvas = canvas;
        //       const clock = new Clock();
        //       let mixer: AnimationMixer;
        //       self.platform = new WechatPlatform(canvas);
        //       PLATFORM.set(self.platform);

        //       const renderer = new WebGL1Renderer({ canvas, antialias: true, alpha: true });
        //       const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 0.25, 100);
        //       camera.position.set(5, 3, 10);
        //       camera.lookAt(new Vector3(0, 2, 0));

        //       const scene = new Scene();
        //       self.currentScene = scene;
        //       const gltfLoader = new GLTFLoader();
        //       const textureloader = new TextureLoader();
        //       const controls = new OrbitControls(camera, canvas);
        //       controls.enableDamping = true;
        //       controls.maxDistance = 15;
        //       controls.minDistance = 5;
        //       controls.update();

        //       textureloader.loadAsync("https://tmp.linhongxu.com/env.png").then((envMap) => {
        //         toEnvMap(envMap);
        //         scene.environment = envMap;
        //       });

        //       gltfLoader
        //         .loadAsync("https://txcy.oss-cn-hangzhou.aliyuncs.com/hongljing.glb")
        //         .then((gltf: GLTF) => {
        //           // @ts-ignore
        //           gltf.parser = null;
        //           const model = gltf.scene;
        //           model.position.set(0, -2.5, 1);
        //           model.scale.set(2, 2, 2);
        //           model.rotation.y = Math.PI / 6;
        //           scene.add(model);

        //           mixer = new AnimationMixer(model);
        //           const anima1 = mixer.clipAction(gltf.animations[0]);
        //           anima1.setLoop(LoopOnce, 10000);
        //           anima1.play();
        //         });

        //       renderer.toneMapping = ACESFilmicToneMapping;
        //       renderer.toneMappingExposure = 0.6;
        //       renderer.outputEncoding = sRGBEncoding;
        //       scene.add(new AmbientLight(0xffffff, 0.4));
        //       // scene.add(new DirectionalLight(0xffffff, 1.0));
        //       renderer.setSize(canvas.width, canvas.height);
        //       renderer.setPixelRatio($window.devicePixelRatio);

        //       const render = () => {
        //         if (!self.disposing) self.frameId = $requestAnimationFrame(render);
        //         mixer?.update(clock.getDelta());
        //         controls.update();
        //         renderer.render(scene, camera);
        //       };
        //       render();
        //     });
        // }, 5000);
    },

    onLoad: function (options) {
        let self = this;
        let id = options.id;
        let type = options.type;
        console.log(type, "类型");
        self.setData({
            id: id,
            type: type,
            // showLoading: false,
            // showResult: true,
        });
        self.scan();

        // this.playVoice()//停止播放声音
        // this.initGLT()
    },

    onUnload() {
        this.disposing = true;
        $cancelAnimationFrame(this.frameId);
        PLATFORM.dispose();
        this.runningCrs = false;
        this.listener.stop();
        this.stopVoice(); //停止播放声音
    },

    initModel() {
        let self = this;
        console.log("点击");
        this.setData(
            {
                showResult: true,
                showLoading: false,
            },
            function () {
                self.initGLT();
            }
        );
    },

    initGLT() {
        let self = this;
        wx.createSelectorQuery()
            .select("#mainCanvas")
            .node()
            .exec((res) => {
                const canvas = res[0].node;
                self.canvas = canvas;
                const clock = new Clock();
                let mixer: AnimationMixer;
                self.platform = new WechatPlatform(canvas);
                PLATFORM.set(self.platform);

                const renderer = new WebGL1Renderer({ canvas, antialias: true, alpha: true });
                const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 0.25, 100);
                camera.position.set(0, 4, 12);
                const scene = new Scene();
                self.currentScene = scene;
                const gltfLoader = new GLTFLoader();
                const textureloader = new TextureLoader();
                // const controls = new OrbitControls(camera, canvas);
                // controls.enableDamping = true;
                // controls.maxDistance = 15;
                // controls.minDistance = 5;
                // controls.update();

                textureloader.loadAsync("https://tmp.linhongxu.com/env.png").then((envMap) => {
                    toEnvMap(envMap);
                    scene.environment = envMap;
                });
                let gltPath = "";
                if (this.data.type == 1) {
                    gltPath = "https://txcy.oss-cn-hangzhou.aliyuncs.com/hongljing.glb";
                } else {
                    gltPath = "https://txcy.oss-cn-hangzhou.aliyuncs.com/biaozhun.glb";
                }
                gltfLoader.loadAsync(gltPath).then((gltf: GLTF) => {
                    // @ts-ignore
                    gltf.parser = null;
                    const model = gltf.scene;
                    model.lookAt(new Vector3(0, 2.5, 12));
                    scene.add(model);

                    mixer = new AnimationMixer(model);
                    const anima1 = mixer.clipAction(gltf.animations[0]);
                    console.log(anima1, "对象......");
                    self.animal = anima1;
                    // anima1.setLoop(LoopOnce, 10000);
                    // anima1.setLoop();
                    anima1.play();
                    self.playVoice();
                });

                renderer.toneMapping = ACESFilmicToneMapping;
                renderer.toneMappingExposure = 0.6;
                renderer.outputEncoding = sRGBEncoding;
                scene.add(new AmbientLight(0xffffff, 0.4));
                // scene.add(new DirectionalLight(0xffffff, 1.0));
                renderer.setSize(canvas.width, canvas.height);
                console.log(canvas.width, canvas.height, $window.devicePixelRatio, "三个值");
                renderer.setPixelRatio($window.devicePixelRatio);
                const render = () => {
                    if (!self.disposing) self.frameId = $requestAnimationFrame(render);
                    mixer?.update(clock.getDelta());
                    // controls.update();
                    renderer.render(scene, camera);
                };
                render();
            });
    },

    scan: function () {
        this.runningCrs = true;
        this.showLoading("识别中");
    },

    // 播放声音
    playVoice() {
        let self = this;
        if (this.data.type == 1) {
            avatarSound.src = "https://txcy.oss-cn-hangzhou.aliyuncs.com/dongmenglu.mp3";
        } else {
            avatarSound.src = "https://txcy.oss-cn-hangzhou.aliyuncs.com/jing.mp3";
        }
        avatarSound.play();
        avatarSound.onEnded((res) => {
            console.log("播放结束!", self.animal);
            self.animal.stop();
        });
    },

    // 停止播放声音
    stopVoice() {
        avatarSound.src = "";
        avatarSound.stop();
    },

    /**
     * 生成token
     */
    /**
     * 生成token
     */
    queryToken: function () {
        const obj = {
            apiKey: this.data.config.apiKey,
            expires: 86400,
            timestamp: Date.now(),
            acl: `[{"service":"ecs:crs","effect":"Allow","resource":["${this.data.config.crsAppId}"],"permission":["READ","WRITE"]}]`,
        };

        const str = Object.keys(obj)
            .sort()
            .map((k) => k + obj[k])
            .join("");
        obj.signature = CryptoJS.SHA256(str + this.data.config.apiSecret, "").toString();

        return new Promise((resolve, reject) => {
            wx.request({
                url: "https://uac.easyar.com/token/v2",
                method: "post",
                data: obj,
                header: {
                    "content-type": "application/json",
                },
                success: (res) => resolve(res.data),
                fail: (err) => reject(err),
            });
        });
    },

    onCameraInit() {
        //找到canvas对象
        const query = wx.createSelectorQuery();
        query
            .select("#capture")
            .fields({
                node: true,
            })
            .exec((res) => {
                const canvas = res[0].node;
                //设置canvas内部尺寸为480*640，frame-size="medium"的设置下相机帧大多是480*640
                canvas.width = 480;
                canvas.height = 640;
                this.canvas = canvas;
                this.crsClient = new CrsClient(this.data.config, this.canvas);
                //开始监听相机帧
                let cameraContext = wx.createCameraContext();
                console.log("监听");
                this.listener = cameraContext.onCameraFrame((frame) => {
                    if (!this.canvas) return;
                    // let canvas = this.canvas;
                    //如果尺寸不匹配，就修改canvas尺寸以适应相机帧
                    // if (canvas.width !== frame.width || canvas.height !== frame.height) {
                    //     canvas.width = frame.width;
                    //     canvas.height = frame.height;
                    // }
                    this.queryImage(frame);
                });
                this.listener.start();
            });
    },

    queryImage(frame: WechatMiniprogram.OnCameraFrameCallbackResult) {
        let self = this;
        console.log("开始识别");
        if (!this.runningCrs || this.busy || !this.crsClient) return;
        //最短的两次CRS请求间隔
        let now = new Date().getTime();
        if (this.last && now - this.last < this.data.config.minInterval) return;
        this.last = now;
        this.busy = true; //如果正在进行CRS请求，就不允许再次请求
        this.crsClient
            .queryImage(frame)
            .then((res) => {
                console.log(res, "识别结果");
                if (!this.runningCrs) return; //避免在停止后仍然触发
                let result = res && res.result;
                if (!result) return;

                // 表示识别成功
                if (result.target) {
                    console.log("识别成功", result.target.targetId);
                    this.runningCrs = false;
                    this.hideLoading(); //关闭眼睛加载
                    if (this.data.targetIds.find((item) => item.id === result.target.targetId)) {
                        // this.onResult(result.target);
                        let index = this.data.targetIds.findIndex((item) => item.id == result.target.targetId);
                        console.log(index, "索引");
                        this.initGLT(); //初始化模型
                        this.setData({
                            showResult: true, //显示识别结果
                            currentImg: this.data.targetIds[index]["img"],
                        });
                    }
                } else {
                    console.log("识别失败", result.message);
                }
                this.busy = false;
            })
            .catch((e) => {
                this.busy = false;
                console.log(e);
            }); //小程序iOS端不支持finally，所以在then和catch里分别设置busy = false
    },

    // 显示加载
    showLoading(text: string) {
        this.setData({
            showLoading: true,
            showLoadingText: text,
        });
    },

    // 隐藏加载
    hideLoading() {
        this.setData({
            showLoading: false,
        });
    },

    // 打开文本介绍
    openText() {
        this.hideModel();
        this.currentScene.visible = false;
        this.setData({
            showText: true,
        });
    },

    // 隐藏文本介绍
    hideText() {
        this.showModel();
        this.platform;
        this.currentScene.visible = true;
        this.setData({
            showText: false,
        });
    },

    // 拍照合成
    takePhoto() {
        let self = this;
        this.hideModel(); //隐藏模型
        self.setData(
            {
                showCamera: true,
            },
            function () {
                const ctx = wx.createCameraContext();
                ctx.takePhoto({
                    quality: "normal", //high normal low
                    success: (res) => {
                        console.log(res, "拍照");

                        let path = res.tempImagePath;

                        self.drawImage(path);
                    },
                });
            }
        );
    },

    // 拍照合成
    takePhoto1() {
        let self = this;
        this.hideModel(); //隐藏模型
        self.setData(
            {
                showCamera: true,
            },
            function () {
                const ctx = wx.createCameraContext();
                ctx.takePhoto({
                    quality: "normal", //high normal low
                    success: (res) => {
                        console.log(res, "拍照");
                        let path = res.tempImagePath;
                        wx.showLoading({
                            title: "生成中...",
                        });
                        setTimeout(function () {
                            wx.hideLoading();
                            self.drawImage1(path);
                        }, 3000);
                        // this.setData({
                        //     src: res.tempImagePath
                        // })
                    },
                });
            }
        );
    },

    // 合成海报
    drawImage(path: string) {
        console.log("绘图");
        let self = this;
        wx.createSelectorQuery()
            .select("#myCanvas") // 在 WXML 中填入的 id
            .fields({
                node: true,
                size: true,
            })
            .exec((res) => {
                console.log(res, "canvas的返回值");
                // Canvas 对象
                const canvas = res[0].node;
                // 渲染上下文
                const ctx = canvas.getContext("2d");
                const dpr = wx.getSystemInfoSync().pixelRatio;
                canvas.width = res[0].width * dpr;
                canvas.height = res[0].height * dpr;
                console.log(canvas.height * 0.8, canvas.width, dpr, "高度");
                // ctx.scale(1, 1.5)

                let promise1 = new Promise(function (resolve, reject) {
                    const image1 = canvas.createImage();
                    image1.src = path;
                    image1.onload = () => {
                        // 将图片绘制到 canvas 上
                        resolve(image1);
                    };
                });

                let promise2 = new Promise(function (resolve, reject) {
                    const image2 = canvas.createImage();
                    image2.src = "https://txcy.oss-cn-hangzhou.aliyuncs.com/c_canvas_2.png";
                    image2.onload = () => {
                        console.log("绘制");
                        // 将图片绘制到 canvas 上
                        resolve(image2);
                    };
                });

                wx.showLoading({
                    title: "生成中...",
                });

                Promise.all([promise1, promise2]).then((res) => {
                    ctx.drawImage(res[0], 40, 40, 520, 700);
                    ctx.drawImage(res[1], 0, 0, canvas.width, canvas.height);
                    wx.hideLoading();
                });

                self.setData({
                    canvas: canvas,
                });
            });
    },

    // 合成海报
    drawImage1(path: string) {
        let self = this;
        wx.createSelectorQuery()
            .select("#myCanvas") // 在 WXML 中填入的 id
            .fields({
                node: true,
                size: true,
            })
            .exec((res) => {
                // Canvas 对象
                const canvas = res[0].node;
                // 渲染上下文
                const ctx = canvas.getContext("2d");
                const dpr = wx.getSystemInfoSync().pixelRatio;
                canvas.width = res[0].width * dpr;
                canvas.height = res[0].height * dpr;

                // ctx.scale(1, 1.5)
                // const image1 = canvas.createImage()
                // image1.src = path
                // image1.onload = () => {
                //   // 将图片绘制到 canvas 上
                //   ctx.drawImage(image1, 40, 40, 520, 700)
                // }

                // const image2 = canvas.createImage()
                // image2.src = "https://txcy.oss-cn-hangzhou.aliyuncs.com/c_canvas_1.png"
                // image2.onload = () => {
                //   // 将图片绘制到 canvas 上
                //   ctx.drawImage(image2, 0, 0, canvas.width, canvas.height)
                // }

                let promise1 = new Promise(function (resolve, reject) {
                    const image1 = canvas.createImage();
                    image1.src = path;
                    image1.onload = () => {
                        // 将图片绘制到 canvas 上
                        resolve(image1);
                    };
                });

                let promise2 = new Promise(function (resolve, reject) {
                    const image2 = canvas.createImage();
                    image2.src = "https://txcy.oss-cn-hangzhou.aliyuncs.com/c_canvas_1.png";
                    image2.onload = () => {
                        console.log("绘制");
                        // 将图片绘制到 canvas 上
                        resolve(image2);
                    };
                });

                wx.showLoading({
                    title: "生成中...",
                });

                Promise.all([promise1, promise2]).then((res) => {
                    ctx.drawImage(res[0], 40, 40, 520, 700);
                    ctx.drawImage(res[1], 0, 0, canvas.width, canvas.height);
                    wx.hideLoading();
                });

                self.setData({
                    canvas: canvas,
                });
            });
    },

    // 保存海报
    save() {
        var _this = this;
        wx.canvasToTempFilePath({
            // 把画布转化成临时文件
            x: 0,
            y: 0,
            width: 600, // 截取的画布的宽
            height: 800, // 截取的画布的高
            destWidth: 600, // 保存成的画布宽度
            destHeight: 800, // 保存成的画布高度
            fileType: "jpg", // 保存成的文件类型
            quality: 1, // 图片质量
            canvas: _this.data.canvas, // 画布ID
            success(res) {
                console.log(res, "临时图片");
                _this.setData({
                    picTempUrl: res.tempFilePath,
                });
                // 2-保存图片至相册
                wx.saveImageToPhotosAlbum({
                    // 存成图片至手机
                    filePath: res.tempFilePath,
                    success(res2) {
                        wx.hideLoading();
                        wx.showToast({
                            title: "保存成功",
                            duration: 2000,
                        });
                    },
                    fail(res3) {
                        if (res3.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
                            wx.showToast({
                                title: "保存失败，稍后再试",
                                duration: 2000,
                                icon: "none",
                            });
                            wx.hideLoading();
                        } else {
                            wx.showToast({
                                title: "保存失败，稍后再试",
                                duration: 2000,
                                icon: "none",
                            });
                            wx.hideLoading();
                        }
                    },
                });
            },
            fail() {
                wx.showToast({
                    title: "保存失败，稍后再试",
                    duration: 2000,
                    icon: "none",
                });
                wx.hideLoading();
            },
        });
    },

    // 隐藏模型
    hideModel() {
        this.currentScene.visible = false;
    },

    // 显示模型
    showModel() {
        this.currentScene.visible = true;
    },
});
